package com.docmanage.common.utils.file;

import com.docmanage.common.utils.ServletUtils;
import com.docmanage.common.utils.StringUtils;
import com.docmanage.common.utils.spring.SpringUtils;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * Minio 文件存储工具类
 *
 * @author invoice
 */
public class MinioUtil
{
    /**
     * 上传文件
     *
     * @param bucketName 桶名称
     * @param fileName   文件名
     * @throws IOException 异常
     */
    public static String uploadFile(String bucketName, String fileName, MultipartFile multipartFile) throws IOException
    {
        String url;
        MinioClient minioClient = SpringUtils.getBean(MinioClient.class);
        try (InputStream inputStream = multipartFile.getInputStream())
        {
            //获取文件名称后缀
            String  newFileName=setFileName(fileName);
            minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(newFileName).stream(inputStream, multipartFile.getSize(), -1).contentType(multipartFile.getContentType()).build());
            url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(newFileName).method(Method.GET).build());
            url = url.substring(0, url.indexOf('?'));

            String uri = URI.create(url).getPath();
            return ServletUtils.urlDecode(uri);
        }
        catch (Exception e)
        {
            throw new IOException(e.getMessage(), e);
        }
    }


    /**
     * 文件下载
     *
     * @param bucketName 桶名称
     * @param fileName   文件名
     * @throws IOException 异常
     */
    public static void downloadFile(String bucketName,String fileName,
                                      HttpServletResponse response) {

        InputStream inputStream   = null;
        OutputStream outputStream = null;
        try {
            if (StringUtils.isBlank(fileName)) {
                response.setHeader("Content-type", "text/html;charset=UTF-8");
                String data = "文件下载失败";
                OutputStream ps = response.getOutputStream();
                ps.write(data.getBytes("UTF-8"));
                return;
            }
            //获取文件名称后缀
            String  newFileName=setFileName(fileName);
            MinioClient minioClient = SpringUtils.getBean(MinioClient.class);
            outputStream = response.getOutputStream();
            // 获取文件对象
            inputStream =minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(newFileName).build());
            byte[] buf = new byte[1024];
            int length = 0;
            response.reset();
            response.setHeader("Content-Disposition", "attachment;filename=" +
                    URLEncoder.encode(fileName, "UTF-8"));
            response.setContentType("application/octet-stream");
            response.setCharacterEncoding("UTF-8");
            // 输出文件
            while ((length = inputStream.read(buf)) > 0) {
                outputStream.write(buf, 0, length);
            }
            inputStream.close();
        } catch (Throwable ex) {
            response.setHeader("Content-type", "text/html;charset=UTF-8");
            String data = "文件下载失败";
            try {
                OutputStream ps = response.getOutputStream();
                ps.write(data.getBytes("UTF-8"));
            }catch (IOException e){
                e.printStackTrace();
            }
        } finally {
            try {
                outputStream.close();
                if (inputStream != null) {
                    inputStream.close();
                }}catch (IOException e){
                e.printStackTrace();
            }
        }
    }

    public static Boolean delFile(String bucketName,String fileName) {
        MinioClient minioClient = SpringUtils.getBean(MinioClient.class);
        try {
            //获取文件名称后缀
            String  newFileName=setFileName(fileName);
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(newFileName).build());
        } catch (Exception  e) {
           return false;
        }
        return true;
    }

    private static String setFileName(String fileName){
        //获取文件后缀名
        String extension = FilenameUtils.getExtension(fileName);
        String newFileName=fileName;
        if (StringUtils.isNotEmpty(extension)){
            newFileName=extension.concat("/").concat(fileName);
        }
        return newFileName;
    }
}
